Прављење програма¶
Нови пројекат можемо да започнемо тако што у менију изаберемо File \(\to\) New \(\to\) Project. Као језик бирамо Visual C#, док као врсту пројекта треба изабрати Windows forms App (.NET framework). Затим задајемо назив пројекта и место на диску где ће пројекат бити сачуван.
На крају дијалога за започињање новог пројекта помиње се мање јасан појам - решење (solution). У овом контексту, реч „решење” се односи на колекцију од неколико пројеката, који чине одређену целину. То могу бити неколико сличних програма, или библиотеке које сами направимо и програм који их користи и слично. Нови пројекат можемо да додамо постојећем решењу, или да тим пројектом започнемо ново решење.
Када завршимо дијалог за креирање новог пројекта, пред нама је празан прозор - образац (формулар, енгл, Form, па је и код нас у жаргону одомаћен израз форма) који треба да дизајнирамо.
Овде постоји извесна аналогија са папирним формуларима. Претпоставимо да представљамо организацију која корисницима нуди одређену услугу. Да бисмо могли да услужимо корисника, потребно је да нам корисник достави неке податке. Најудобније нам је да податке прикупимо тако што кориснику дамо да попуни формулар. На пример, у пошти корисник уписује у формулар адресу на коју треба да стигне његова препоручена пошиљка. Када попуни (папирни) формулар, корисник га предаје особи која онда покреће поступак пружања услуге.
Софтверски формулар често има исту ту намену (отуда и исто име). За разлику од папирног формулара, када корисник попуни електронски формулар он најчешће може директно да покрене и акцију за пружање услуге (није потребно посредовање друге особе).
При дизајнирању папирног формулара на папир стављамо питања и линије за уписивање одговора, или набројане ставке од којих корисник треба неке да заокружи. Дизајнирање електронског формулара је слично - треба да поставимо одређене компоненте које се зову контроле на формулар који је на почетку пројекта празан. Контроле које обично стављамо на формулар су:
контроле које садрже питања или упутстава за попуњавање
контроле за прихватање података од корисника
контроле за покретање акције
Ускоро ћемо видети да ова подела контрола по намени није стриктна, нити су ово једине намене контрола које користимо, али за сада можемо о контролама да размишљамо као да имају само по једну од ових намена.
Широк избор контрола које можемо да стављамо на формуларе је дат у помоћном прозору који се зове Toolbox (кутија за алат). Уколико у окружењу Visual Studio не видите овај помоћни прозор, можете да га отворите из менија View \(\to\) Toolbox.
Први програм¶
У уводном примеру ћемо употребити пар контрола без којих готово да и нема стварног формулара.
Пример - старост¶
Креирати Windows Forms апликацију, која омогућава кориснику да унесе име и датум рођења, а затим исписује његову старост у данима.
Један начин да обавимо овај задатак је да за сваки тражени податак поставимо на формулар текст који кориснику објашњава шта се од њега очекује, и поред тог текста једно поље за унос текста. Осим тога, поставићемо и дугме на које корисник треба да кликне када заврши са уносом.
За описни текст, који се обично не мења током рада програма, можемо да користимо контролу која се зове лабела. У кутији за алат постоји група Common Controls (уобичајене контроле), у којој можемо да пронађемо контролу Label (лабела, ознака).
Изаберимо лабелу кликом на њу у кутији за алат. Када је изаберемо, она постаје означена као на следећој слици.
Сада можемо да поставимо лабелу на формулар кликом у формулару на место на које желимо да поставимо лабелу (корак борј 2 на слици доле). Ако нисмо задовољни положајем лабеле, можемо мишем да превучемо лабелу на друго место. Након позиционирања лабеле треба да упишемо у њу текст „Име” (да би корисник касније знао шта треба да унесе у поље поред лабеле). За то нам је потребан помоћни прозор Properties (својства). Ако овај прозор није већ отворен, можемо да га отворимо десним кликом на постављену контролу и избором Properties из контекстног менија који је искочио (корак број 3 на слици доле). У прозору са својствима, упишимо поред својства Text (текст) његову нову вредност „Име” уместо „Label1” (корак 4 на слици доле).
Мењањем својства Text лабеле, аутоматски се мења и текст у самој лабели на формулару. Помоћу прозора са својствима можемо да мењамо и друга својства лабеле, на пример:
својство Location, помоћу којег задајемо положај, то јест кординате лабеле у формулару (о координатном систему биће речи нешто касније). Ово својство се обично користи само за фино (прецизно) позиционирање контроле, а за крупна померања лакше је превући контролу мишем.
својство Font, помоћу којег задајемо врсту и величину слова
својство ForeColor, помоћу којег задајемо боју текста лабеле
својство Name, помоћу којег задајемо име контроле у програму
и тако даље. На исти начин можемо да мењамо и својства других контрола, па и самог формулара. Изаберите на пример својства формулара, било кликом на формулар (чиме се у прозору Properties одмах прелази на приказивање својстава формулара), било избором формулара у листи компонената, уоквиреној наранџасто на претходној слици, а затим измените својство Text на „Старост”. Тиме ће се у насловној линији формулара појавити нови наслов.
Поставимо сада контролу TextBox десно од лабеле. Ова контрола служи да корисник у њу упише неки текст (у овом случају своје име) и зваћемо је текстуално поље. Поступак је исти као и за лабелу: пронађемо контролу TextBox у кутији за алат, изаберемо је кликом, а затим је новим кликом у формулар поставимо на жељено место. Међу својствима ове контроле можемо да нађемо својство Name (при врху листе) и да га променимо тако да уместо textBox1 вредност буде tbIme.
За унос датума рођења можемо да употребимо још три текстуална поља. Како ова три податка чине целину за себе, поставићемо најпре на формулар један оквир за груписање (контрола GroupBox), а његово својство Text на „Датум рођења”. Оквир за груписање се у кутији за алат налази у групи Containers (контејнери).
У овом програму поменути оквир нема никакву функцију осим да формулар учини јаснијим кориснику. Сада унутар овог оквира можемо да поставимо три текстуална поља (за унос дана, месеца и године рођења), као и одговарајуће лабеле. Нека имена текстуалних поља (вредности својства Name) буду tbDan, tbMesec i tbGodina, а текстови на лабелама (вредност својства Text) „дан”, „месец” и „година”.
Потребно је још дугме на које ће корисник да кликне када заврши са уносом. Дугме је представљено контролом Button из кутије за алат. Натпис на дугмету (својство Text) поставимо на „ОК”, а име контроле (својство Name) на btnOK.
Тиме смо довршили дизајнирање изгледа формулара, који сада изгледа овако:
Остаје још да испрограмирамо понашање формулара. Од текстуалних поља очекујемо само уобичајено понашање, које кориснику омогућава унос текста, а за то није потребно никакво додатно подешавање. Према томе, потребно је задати само понашање дугмета. Двокликом на дугме стварамо функцију (тачније методу) која ће се извршити када корисник кликне на дугме током извршавања програма.
private void btnOK_Click(object sender, EventArgs e)
{
}
У ту функцију уписујемо наредбе које ће очитати садржај текстуалних поља, обавити потребно рачунање и исписати поруку.
private void btnOK_Click(object sender, EventArgs e)
{
int dr = int.Parse(tbDan.Text);
int mr = int.Parse(tbMesec.Text);
int gr = int.Parse(tbGodina.Text);
DateTime datumRodjenja = new DateTime(gr, mr, dr);
DateTime danas = DateTime.Now;
TimeSpan starost = danas.Subtract(datumRodjenja);
string poruka = string.Format("{0} danas ima {1} dana",
tbIme.Text, (int)starost.TotalDays);
MessageBox.Show(poruka);
}
У прва три реда ове функције читамо својство Text трију текстуалних поља (приметите имена контрола tbDan, tbMesec, tbGodina, која смо задали током дизајнирања формулара). Очитана својства су типа string, па треба да их конвертујемо у целе бројеве.
У редовима који следе смо се увелико ослонили на готове функције богате .NET (чита се дот-нет) библиотеке. Као што видимо, бибилиотека на пример пружа подршку за рад са датумима и временима (користили смо објекте који представљају датум и време, очитавање текућег датума и времена са системског часовника, рачунање разлике два датума, објекат који представља одређени временски распон и изражавање тог распона у данима). Све ово је само мали детаљ у мору функционалности која постоји у .NET библиотеци. Оваквих корисних детаља има толико много да је практично неизводљиво (и бесмислено) учити их редом. Уместо тога, уобичајена пракса чак и међу професионалцима је да када им је потребна нека функционалност (за коју претпостављају да постоји као готова али је нису раније користили или су заборавили како се користи) потраже додатне информације на интернету. Огромне су шансе да је неко пре тога већ поставио слично питање и добио одговор, а уколико је баш потребно, можемо и сами да поставимо питање и сачекамо да неко одговори. Наравно, није добро механички копирати готове делове туђих програма у свој код, већ је потребно разумети пронађени пример и прилагодити га свом програму.
Могли смо и да напишемо програм који се мање ослања на библиотеку, али то није једноставно као што можда изгледа. Било би потребно узети у обзир које године су преступне и колико који месец има дана. Такав програм би био дужи, сложенији и ризиковали бисмо да направмо грешке у рачунању. Зато, иако претходно решење изгледа тешко за реализацију (можда се питате: „све је то лепо и отприлике јасно, али како ја да знам шта све постоји и како се зове?”), треба настојати да се пронађе и искористи постојећа функционалност из библиотека. Ово је вештина која се вежба и зато подстичемо читаоце да храбро крену у истраживање.
Ово је прва употребљива верзија програма Старост. Програм можемо да покренемо на уобичајени начин (на пример притиском на тастер F5) и испробамо га. Видимо да када се у поља за датум унесу одговарајући бројеви, програм лепо ради. Међутим, ако се не унесу бројеви него нешто друго, долази до грешке при извршавању програма:
Ова порука значи да улазни стринг (саржај текстуалног поља) није у исправном формату и зато претварање (конверзија) тог стринга у број није била изводљива. Пошто оно што смо тражили од програма није могло да се уради, програм је генерисао такозвани изузетак (енгл. exception). Изузетак који није ухваћен и обрађен доводи до грешке при извршавању програма (runtime error), што значи да програм прекида са извршавањем јер не зна шта да ради у насталој ситуацији. У жаргону кажемо да програм „пукне” (the program breaks).
Слично се дешава и када се унесу бројеви који не представљају исправан датум:
У овом случају програм „пуца” нешто касније и са другачијом поруком, али суштина је иста: подаци нису били одговарајући и нека од наредби није могла да буде извршена.
Да бисмо избегли овакав ружан исход, можемо досадашње наредбе да убацимо у блок за обраду изузетака:
private void btnOK_Click(object sender, EventArgs e)
{
try
{
int dr = int.Parse(tbDan.Text);
int mr = int.Parse(tbMesec.Text);
int gr = int.Parse(tbGodina.Text);
DateTime datumRodjenja = new DateTime(gr, mr, dr);
DateTime danas = DateTime.Now;
TimeSpan starost = danas.Subtract(datumRodjenja);
string poruka = string.Format("{0} danas ima {1} dana",
tbIme.Text, (int)starost.TotalDays);
MessageBox.Show(poruka);
}
catch (Exception exc)
{
MessageBox.Show("Unesite ispravan datum.");
}
}
Сада програм ради нешто смислено и у случају да корисник не унесе исправан датум (опомиње корисника да унесе исправан датум).
Из овог примера вреди запамтити и то да се наредбом
MessageBox.Show(s);
приказује нови прозор са кратком поруком. Поруку коју желимо да прикажемо наводимо као аргумент типа стринг.
Још боље решење би било да се кориснику понуди унос датума помоћу контроле која је специјализована за то, јер онда корисник не може ни да унесе неисправан датум. Такво решење ћемо представити нешто касније.